AIR CLI Integration: hyperlink Run ID/Experiment, MLflow run name, and i/L in air list - #6260
Merged
Merged
Conversation
…add i/L in `air list` Enriches the interactive `air list` picker toward the Python CLI: - Run ID and Experiment cells are now OSC-8 hyperlinks (job-run page and MLflow experiment page, org-pinned), alongside the existing MLflow link. Underlined only when actually linked; piped/NO_COLOR output stays plain. - The MLflow column shows the MLflow run name (with a …<id8> fallback) instead of a truncated URL, reusing fetchMLflowRunName/mlflowRunLabel. Cached for terminal runs. - `i` opens a scrollable run-details pane and `L`/`l` a logs snapshot pane (bubbles/viewport); `esc` returns to the list. `enter` still opens MLflow. The logs snapshot is a one-shot tail (staticView) so an active run can't hang the pane. Co-authored-by: Isaac
Collaborator
Integration test reportCommit: 1177284
8 interesting tests: 4 RECOVERED, 4 SKIP
Top 1 slowest tests (at least 2 minutes):
|
air listair list
maggiewang-db
approved these changes
Aug 14, 2026
| m := next.(listModel) | ||
|
|
||
| // A resolved detailMsg fills the pane. | ||
| next, _ = m.Update(detailMsg{title: "Run details", body: "hello from the detail pane"}) |
Contributor
There was a problem hiding this comment.
Here you hardcoded "Run details" but elsewhere it's "Run Details". Can you keep the capitalization consistent?
| if m.fetcher != nil && len(m.rows) > 0 { | ||
| m.mode = modeDetail | ||
| m.detailLoading = true | ||
| m.detailTitle = "Logs snapshot" |
Contributor
There was a problem hiding this comment.
Here you set the title to "Logs snapshot" but elsewhere it's "Logs Snapshot". Let's keep the capitalization consistent.
Comment on lines
+195
to
+206
| case detailMsg: | ||
| m.detailLoading = false | ||
| if msg.err != nil { | ||
| m.detailContent = fmt.Sprintf("Error: %v", msg.err) | ||
| } else { | ||
| m.detailContent = msg.body | ||
| } | ||
| m.detailTitle = msg.title | ||
| m.viewport.SetContent(m.detailContent) | ||
| m.viewport.GotoTop() | ||
| m.mode = modeDetail | ||
| return m, nil |
Contributor
There was a problem hiding this comment.
Here is an issue Claude found:
i/L set mode = modeDetail and kick off an async GetRun/logs fetch. If the user hits esc back to the list before that fetch resolves, this handler unconditionally flips mode back to modeDetail, snapping them out of the list into a pane they already dismissed. Suggest dropping the result if we're no longer in detail mode:
Suggested change
| case detailMsg: | |
| m.detailLoading = false | |
| if msg.err != nil { | |
| m.detailContent = fmt.Sprintf("Error: %v", msg.err) | |
| } else { | |
| m.detailContent = msg.body | |
| } | |
| m.detailTitle = msg.title | |
| m.viewport.SetContent(m.detailContent) | |
| m.viewport.GotoTop() | |
| m.mode = modeDetail | |
| return m, nil | |
| case detailMsg: | |
| // If the user pressed esc back to the list before async fetch | |
| // completes, drop the late result. | |
| if m.mode != modeDetail { | |
| return m, nil | |
| } | |
| m.detailLoading = false | |
| if msg.err != nil { | |
| m.detailContent = fmt.Sprintf("Error: %v", msg.err) | |
| } else { | |
| m.detailContent = msg.body | |
| } | |
| m.detailTitle = msg.title | |
| m.viewport.SetContent(m.detailContent) | |
| m.viewport.GotoTop() | |
| return m, nil |
…detail results
- Use title case ("Run Details" / "Logs Snapshot") for the pane title in both
the loading and resolved states (was mixed case).
- Drop a detailMsg that arrives after the user has escaped back to the list, so
a slow GetRun/logs fetch can't snap them back into a pane they dismissed.
Co-authored-by: Isaac
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Enriches the interactive
air listpicker toward the Python AIR CLI.Changes
NO_COLORoutput stays plain (no escapes).…<id8>fallback) instead of a truncated…/runs/<id>URL. Reuses the existingfetchMLflowRunName/mlflowRunLabel; the resolved label is cached for terminal runs.iandL/lopen an in-TUI scrollable pane —ishows run details (the same styled view asair get),Lshows a logs snapshot (bubbles/viewport).escreturns to the list with the cursor preserved.enterstill opens MLflow in the browser.Notes
staticView), so viewing an active run’s logs can’t hang the pane waiting on a live stream.renderRunText/fetchLogs) output; since the capture target isn’t a TTY they render in the ASCII profile (text and box borders intact, no color). A forced-color pane is a possible follow-up.mlflowExperimentURLfor the experiment link (no?o=, consistent with the other ML URLs) rather than adding a parallel helper.Tests
i→ detail-mode transition, detail-pane content +escback, run-name label.air list): the MLflow column now shows the run name; golden regenerated. Full air unit + acceptance suite,go vet,gofmt, andgolangci-lintall pass.This pull request and its description were written by Isaac.
